<template>
  <div class="img-upload clearfix" v-loading.fullscreen.lock="hasLoading&&uploading&&hasFullLoading">
    <el-upload ref="imgUpload" class="img-upload-input" :class="{'can-upload':!readonly&&!uploading}" :accept="accept" :show-file-list="false"
      :multiple="false" :data="requestData" :auto-upload="false" :disabled="readonly||uploading" :drag="drag" action=""
      :on-change="handleUploadChange">
      <i v-if="imgUrl===''" class="el-icon-plus img-uploader-icon" :style="uploadIconSize"></i>
      <div v-else class="img-upload-content clearfix" :style="imageSize">
        <el-image :src="imgUrl" fit="scale-down"></el-image>
        <div v-if="imgHandle&&imgHandle.length>0" class="fixed-div upload-img-handle">
          <div class="upload-mask"></div>
          <div class="upload-img-btns">
            <span v-if="imgHandle.indexOf('preview')!==-1" title="预览" @click.stop="previewImg">
              <i class="el-icon-zoom-in"></i>
            </span>
            <span v-if="!readonly&&imgHandle.indexOf('delete')!==-1" title="删除" @click.stop="deleteImg">
              <i class="el-icon-delete"></i>
            </span>
          </div>
        </div>
      </div>
      <div v-if="uploading" class="fixed-div uploader-progress">
        <div class="upload-mask"></div>
        <el-progress type="circle" :width="progressWidth" :percentage="progressValue"></el-progress>
      </div>
    </el-upload>

    <el-image v-if="imgUrl!==''" ref="previewImgDiv" class="previewImg" :src="imgUrl" fit="scale-down" :preview-src-list="[imgUrl]"></el-image>
  </div>
</template>

<script>
  import UploadFileApi from 'services/uploadFileApi';

  export default {
    props: {
      value: {
        type: String,
        required: true
      },
      imgWidth: {
        type: [String, Number],
        default: 250
      },
      imgHeight: {
        type: [String, Number],
        default: 250
      },
      readonly: {
        type: Boolean,
        default: false
      },
      requestData: Object,
      autoUpload: {
        type: Boolean,
        default: true
      },
      accept: {
        type: String,
        default: 'image/*'
      },
      drag: {
        type: Boolean,
        default: false
      },
      uploadCheckMethod: Function,
      errorMsg: {
        type: String,
        default: '请选择图片格式文件上传'
      },
      imgHandle: {
        type: Array,
        default: function () {
          return ['preview', 'delete'];
        }
      },
      hasFullLoading: {
        type: Boolean,
        default: false
      },
      hasLoading: {
        type: Boolean,
        default: true
      }
    },

    watch: {
      value() {
        if (this.inputValue !== null) {
          this.inputValue = null;
          return;
        }

        this.imgUrl = this.value;
      }
    },

    computed: {
      imageSize() {
        let imgWidth = this.imgWidth;
        if (typeof imgWidth === 'number') {
          imgWidth = imgWidth + 'px';
        }
        let imgHeight = this.imgHeight;
        if (typeof imgHeight === 'number') {
          imgHeight = imgHeight + 'px';
        }
        return {
          width: imgWidth,
          height: imgHeight
        }
      },
      uploadIconSize() {
        let size = this.imageSize;
        size = _.cloneDeep(size);
        size.lineHeight = size.height;
        return size;
      },
      progressWidth() {
        let imgWidth = this.imgWidth;
        let imgHeight = this.imgHeight;
        let width = Math.min(imgWidth, imgHeight, 126);
        return width - 10;
      }
    },

    data() {
      return {
        uploading: false,
        imgUrl: this.value,
        inputValue: null,
        progressValue: 0,
        uploadField: null
      };
    },

    methods: {
      handleUploadChange(file) {
        let status = file.status;
        if (status !== 'ready') {
          return;
        }

        this.checkUploadImgValid(file).then(flag => {
          if (!flag) {
            return;
          }

          if (this.autoUpload) {
            this.uploadImg(file);
            return;
          }
          let imgUrl = this.imgUrl;
          this.imgUrl = URL.createObjectURL(file.raw);
          this.uploadField = file;
          let type = imgUrl === '' ? 'add' : 'update';
          this.$emit('change', file, type);
        });
      },

      checkUploadImgValid(file) {
        let uploadCheckMethod = this.uploadCheckMethod;
        if (uploadCheckMethod !== undefined) {
          if (typeof uploadCheckMethod !== 'function') {
            throw new Error('uploadCheckMethod is not a function');
          }
          return uploadCheckMethod(file.raw);
        }

        let type = file.raw.type;
        let valid = type.indexOf('image/') === 0;
        if (!valid) {
          this.$message.error({
            message: this.errorMsg,
            duration: 2000
          });
        }
        return Promise.resolve(valid);
      },

      uploadImg(file) {
        this.progressValue = 0;
        this.uploading = true;

        return UploadFileApi.uploadImg(file.raw, ({
          percent
        }) => {
          this.progressValue = _.round(percent, 2);
        }).then(url => {
          this.uploading = false;
          if (this.autoUpload) {
            this.imgUrl = URL.createObjectURL(file.raw);
          } else {
            this.uploadField = null;
          }
          this.$refs.imgUpload.clearFiles();
          this.inputValue = url;
          this.$emit('input', url);
          this.$emit('upload-success', url);
          return url;
        }).catch(error => {
          this.uploading = false;
          this.$refs.imgUpload.clearFiles();
          this.$alert('图片上传失败');
          this.$emit('upload-error', error);
          throw error;
        });
      },

      previewImg() {
        $(this.$refs['previewImgDiv'].$el).find('img').click();
      },

      deleteImg() {
        let imgUrl = this.imgUrl;
        this.imgUrl = '';
        this.uploadField = null;
        this.inputValue = '';
        this.$emit('input', '');
        this.$emit('delete', imgUrl);
      },

      submit() {
        let uploadField = this.uploadField;
        if (uploadField === null) {
          this.$emit('upload-success', this.value);
          return Promise.resolve(this.value);
        }
        return this.uploadImg(uploadField);
      },

      checkImgExist() {
        return this.imgUrl !== '';
      }
    }
  };

</script>

<style lang="scss">
  .img-upload .img-upload-input {
    border: 1px dashed transparent;
    border-radius: 6px;
    position: relative;
    float: left;
    overflow: hidden;
    min-width: 100px;
    min-height: 100px;

    &.can-upload {
      border: 1px dashed #d9d9d9;

      &:hover {
        border-color: #409EFF;
      }

      .el-upload {
        cursor: pointer;
        min-width: 100px;
        min-height: 100px;
      }
    }

    .el-upload {
      cursor: initial;
      display: block;
    }

    .img-uploader-icon {
      font-size: 28px;
      color: #8c939d;
      text-align: center;
    }

    .img-upload-content {
      position: relative;

      .el-image {
        width: 100%;
        height: 100%;
      }

      .upload-img-handle {
        opacity: 0;
        transition: opacity .3s;
        -moz-transition: opacity .3s;
        -webkit-transition: opacity .3s;
        -o-transition: opacity .3s;

        .upload-img-btns {
          position: absolute;
          left: 0;
          width: 100%;
          height: 36px;
          top: calc(50% - 18px);
          color: #ffffff;
          font-size: 20px;
          line-height: 36px;

          >span {
            cursor: pointer;

            &:hover {
              color: #3a8ee6;
            }
          }

          >span+span {
            margin-left: 15px;
          }
        }
      }

      &:hover .upload-img-handle {
        opacity: 1;
      }
    }

    .fixed-div {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
    }
  }

  .img-upload {
    position: relative;

    .upload-mask {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      background: #000000;
      filter: alpha(opacity=50);
      opacity: 0.5;
      -moz-opacity: 0.5;
    }

    .uploader-progress {
      position: relative;

      .el-progress {
        @extend .center-middle;
      }

      .el-progress__text {
        color: #ffffff;
      }
    }

    .previewImg {
      position: absolute;
      left: 0;
      top: 0;

      >img,
      .el-image__error {
        display: none;
      }
    }
  }

</style>
